package com.vectz.mgt;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Vector;

import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;

import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

import com.ait.lsp.msm.ui.decorator.component.button.DefaultButton;
import com.ait.lsp.msm.ui.decorator.container.DefaultFrame;
import com.ait.lsp.msm.ui.decorator.menu.DefaultCheckBoxMenu;
import com.ait.lsp.msm.ui.decorator.menu.DefaultMenu;
import com.ait.lsp.msm.ui.decorator.menu.DefaultMenuItem;
import com.ait.lsp.msm.ui.decorator.table.DefaultTable;
import com.ait.lsp.msm.ui.decorator.util.Message;
import com.ait.lsp.msm.ui.decorator.util.SwingUtil;
import com.vectz.mgt.action.ActionCodegenAction;
import com.vectz.mgt.action.DAOCodegenAction;
import com.vectz.mgt.action.ExcelAction;
import com.vectz.mgt.action.IActionCodegenAction;
import com.vectz.mgt.action.IDAOCodegenAction;
import com.vectz.mgt.action.IndexPageCodegenAction;
import com.vectz.mgt.action.JsfAddCodegenAction;
import com.vectz.mgt.action.JsfConfirmCodegenAction;
import com.vectz.mgt.action.JsfListCodegenAction;
import com.vectz.mgt.action.JsfResultCodegenAction;
import com.vectz.mgt.action.ModelCodegenAction;
import com.vectz.mgt.action.XmlPageCodegenAction;
import com.vectz.mgt.model.Entity;
import com.vectz.mgt.model.EntityOverview;
import com.vectz.mgt.util.Log;
import com.vectz.mgt.util.Util;
/**
 * @author ai-t.vn
 * 
 */
public class GenGUI extends DefaultFrame {

	private static final long serialVersionUID = 3281754183762158277L;
	// Declared variables
	private JScrollPane sclChannel = new JScrollPane();
	private DefaultButton btnBrowser = new DefaultButton();
	private DefaultButton btnLoad = new DefaultButton();
	private JTextField txtExcelPath = new JTextField();
	private DefaultButton btnGenerate = new DefaultButton();
	static JCheckBox ckbSelectAllSheet = new JCheckBox();

	// menu
	private JMenuBar mnuMain = new JMenuBar();
	// menu File
	private DefaultMenu mnuFile = new DefaultMenu("File", true);
	private DefaultMenuItem mnuExit = new ExitMenu();
	// menu setting
	private DefaultMenu mnuSetting = new DefaultMenu("Setting", true);
	private static DefaultCheckBoxMenu mnuVectzwork = (DefaultCheckBoxMenu) new VectzworkMenu();
	// menu Help
	private DefaultMenu mnuHelp = new DefaultMenu("Help", true);
	private DefaultMenuItem mnuAbout = new AboutMenu();

	String[] headerDivision = new String[] { "No ", "   ", "Sheet name" };
	ArrayList<String> listSheet = null;

	private FileInputStream fis = null;
	private HSSFWorkbook wb = null;

	// ExitMenu class
	class ExitMenu extends DefaultMenuItem {
		public ExitMenu() {
			super("Exit",'x',null);
		}
		public void execute() {
			doExit();
		}
	}
	static class VectzworkMenu extends DefaultCheckBoxMenu {
		public VectzworkMenu() {
			super("Using Vectzwork", true);
		}
		public void execute() {
		}
	}

	// AboutMenu class
	static class AboutMenu extends DefaultMenuItem {
		public AboutMenu() {
			super("About MMGS", 'A', KeyStroke.getKeyStroke(KeyEvent.VK_F1,
					InputEvent.CTRL_MASK));
		}
		public void execute() {
			Runnable runable = new Runnable() {
				public void run() {
					new AboutBox();
				}
			};
			SwingUtilities.invokeLater(runable);
		}
	}

	// Construction
	public GenGUI() {
		try {
			jbInit();

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static DefaultTable tblSheet = new DefaultTable() {
	
		 
		
		public Component prepareRenderer(TableCellRenderer renderer, int row,
				int column) {
			Component returnComp = super.prepareRenderer(renderer, row, column);

			Color alternateColor = new Color(252,242,206);
			Color whiteColor = new Color(255, 255, 255);
			
			if (!returnComp.getBackground().equals(getSelectionBackground())) {
				if(row %2==0)
					returnComp.setBackground(whiteColor);
				 else
				 returnComp.setBackground(alternateColor);

			}
			return returnComp;
		}
	};


	private void jbInit() throws Exception {
		// Set exit on close
		this.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent evt) {
				doExit();
			}
		});


		initPanel();
		generateMenu();
		initTable();
		eventObjectManager();

		setTitle("Master Maintenance Generate System");
		setSize(new Dimension(732, 407));
		this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);

		this.setIconImage(Toolkit.getDefaultToolkit().getImage(
				"images" + System.getProperty("file.separator") + "icon.png"));

		SwingUtil.center(this);
		setResizable(false);
		this.setVisible(true);

	}

	private void generateMenu() {
		this.setJMenuBar(mnuMain);

		// File
		mnuMain.add(mnuFile);
		mnuFile.setMnemonic('F');
		mnuFile.add(mnuExit);
		mnuExit.addActionListener(this);
		
		// Setting
		mnuMain.add(mnuSetting);
		mnuSetting.add(mnuVectzwork);
		mnuVectzwork.addActionListener(this);

		// About
		mnuMain.add(mnuHelp);
		mnuHelp.setMnemonic('H');
		mnuHelp.add(mnuAbout);
		mnuAbout.addActionListener(this);
	}

	private void initPanel(){
		// Set layout for the panel
		this.getContentPane().setLayout(null);
		txtExcelPath.setPreferredSize(new Dimension(450, 200));
		txtExcelPath.setBounds(new Rectangle(60, 35, 450, 25));

		btnBrowser.setPreferredSize(new Dimension(90, 25));
		btnBrowser.setMaximumSize(new Dimension(90, 25));
		btnBrowser.setBounds(new Rectangle(525, 35, 70, 25));
		btnBrowser.setText("Browse...");

		btnLoad.setPreferredSize(new Dimension(90, 25));
		btnLoad.setMaximumSize(new Dimension(90, 25));
		btnLoad.setBounds(new Rectangle(600, 35, 70, 25));
		btnLoad.setText("Load");

		// Generate button
		btnGenerate.setBounds(new Rectangle(587, 325, 123, 25));
		btnGenerate.setText("Generate file");

		// Scroll panel
		sclChannel.setAlignmentX((float) 0.5);
		sclChannel.setPreferredSize(new Dimension(250, 100));
		sclChannel.setBounds(new Rectangle(11, 74, 700, 240));
		sclChannel.setViewportView(tblSheet);

		// Add objects to main panel
		this.getContentPane().add(sclChannel, null);
		this.getContentPane().add(ckbSelectAllSheet, null);
		this.getContentPane().add(txtExcelPath, null);
		this.getContentPane().add(btnBrowser, null);
		this.getContentPane().add(btnLoad, null);
		this.getContentPane().add(btnGenerate, null);
	}
	private void initTable() {

		DefaultTableModel model = new DefaultTableModel(null, Util
				.arrayToVector(headerDivision));
		tblSheet.setModel(model);
		tblSheet.getTableHeader().setPreferredSize(new Dimension(0, 15));
		tblSheet.setDefaultRenderer(String.class,
				new DefaultTableCellRenderer());
		
		for (int i = 0; i < 3; i++) {
			TableColumn column = tblSheet.getColumnModel().getColumn(i);
			if (i == 0)
				column.setMaxWidth(27);
			if (i == 1)
				column.setMaxWidth(25);
			if (i == 2)
				column.setPreferredWidth(600);
		}

		tblSheet.setRowHeight(20);
		tblSheet.setFont( new Font("Dialog.plain", Font.PLAIN, 11));
		tblSheet.getTableHeader().setFont(new Font("Dialog.plain", Font.PLAIN, 11));
		tblSheet.getColumnModel().getColumn(0).setResizable(false);
		sclChannel.add(ckbSelectAllSheet);
		ckbSelectAllSheet.setSize(20, 12);
		ckbSelectAllSheet.setLocation(30, 3);
		ckbSelectAllSheet.setText("");
	}

	private void generateTableValue(String excelFile) {

		try {
			if (!Util.isEmpty(excelFile)) {
				if (Util.isValidFile(excelFile)) {
					fis = new FileInputStream(excelFile);
					wb = new HSSFWorkbook(fis);
					listSheet = Util.getListSheetName(wb);
				} else {
					Message
							.showErrorMsg(this, excelFile
									+ "\nFile is invalid.");
				}

			} else {
				Log.log(Log.WARN,"Please choice excel file");
				Message.showErrorMsg(this, "Please choice excel file!");
			}
		} catch (FileNotFoundException e) {
			Log.log(Log.ERROR,"File does not exist: "+e);
			Message.showErrorMsg(this, "Please choice excel file!");
		} catch (Exception e) {
			e.printStackTrace();
		}

		DefaultTableModel model = (DefaultTableModel) tblSheet.getModel();
		if (listSheet != null) {
			for (int i = 0; i < listSheet.size(); i++) {
				String sheetName = listSheet.get(i);
				Vector v = new Vector();
				v.add(String.valueOf(i + 1));
				v.add(Boolean.valueOf("false"));
				v.add(sheetName);
				model.addRow(v);
			}
		}
	}

	private void eventObjectManager() {
		btnGenerate.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				doGenerate();
			}
		});

		btnBrowser.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				JFileChooser chooser = new JFileChooser();
				int returnVal = chooser.showOpenDialog(GenGUI.this);
				if (returnVal == JFileChooser.APPROVE_OPTION) {
					try {
						txtExcelPath.setText(new String(chooser.getSelectedFile().toString().getBytes(),"Shift_JIS"));
					} catch (UnsupportedEncodingException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}

				}
			}
		});
		btnLoad.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				// reset table data
				if (tblSheet.getRowCount() != 0) {
					int i = tblSheet.getRowCount() - 1;
					while (i >= 0) {
						((DefaultTableModel) tblSheet.getModel()).removeRow(i);
						i--;
					}
				}

				generateTableValue(txtExcelPath.getText());
				sclChannel.repaint();
				ckbSelectAllSheet.setSelected(false);
			}
		});

		tblSheet.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent e) {
				int row = tblSheet.getSelectedRow();
				int col = tblSheet.getSelectedColumn();
				// column checkbox
				if (col == 1) {

					if (tblSheet.getValueAt(row, col).toString().equals("true")) {
						tblSheet.setValueAt(Boolean.valueOf("false"), row, col);
						ckbSelectAllSheet.setSelected(false);

					} else {
						tblSheet.setValueAt(Boolean.valueOf("true"), row, col);
						// check for all is selected
						int nSelected = 0;
						for (int i = 0; i < tblSheet.getRowCount(); i++) {
							if (tblSheet.getValueAt(i, 1).toString().equals(
									"true")) {
								nSelected++;
							}
						}
						if (nSelected == tblSheet.getRowCount())
							ckbSelectAllSheet.setSelected(true);

					}
					tblSheet.repaint();
				}

			}
		});
		// event check all
		ckbSelectAllSheet
				.addActionListener(new java.awt.event.ActionListener() {
					public void actionPerformed(java.awt.event.ActionEvent evt) {
						// Set checkbox of all sheet in table is true (marked)
						if (listSheet != null) {
							if (ckbSelectAllSheet.isSelected() == true) {
								for (int i = 0; i < listSheet.size(); i++)
									tblSheet.setValueAt(
											Boolean.valueOf("true"), i, 1);
							} else {
								// Set checkbox of all sheet in table is false
								// (unmarked)
								for (int i = 0; i < listSheet.size(); i++)
									tblSheet.setValueAt(Boolean
											.valueOf("false"), i, 1);
							}
						}
					}
				});
		// end check all
	}

	private Vector<Integer> getMultiSeletedChannelRow() {
		Vector<Integer> rowSelect = new Vector<Integer>();
		// Checkbox column
		int colSelect = 1;
		String strSelect;

		for (int i = 0; i < tblSheet.getRowCount(); i++) {
			strSelect = tblSheet.getModel().getValueAt(i, colSelect).toString();
			if (strSelect.compareToIgnoreCase("true") == 0) {
				rowSelect.add(i);
			}
		}

		if (rowSelect.size() < 1) {
			// none select
			Log.log(Log.ERROR,"Not select any row");
			Message.showWarningMsg(this, "Please select at least one sheet!");

		}
		return rowSelect;
	}

	public void doGenerate() {
		Iterator<Integer> iter = getMultiSeletedChannelRow().iterator();
		boolean result = true;
		if (!iter.hasNext())
			return;
		while (iter.hasNext()) {
			int row = iter.next().intValue();
			try {
				if(!Util.isValidFile(txtExcelPath.getText())){
					result = false;
					Log.log(Log.ERROR,txtExcelPath.getText() +" does not valid.");
					break;
				}
				FileInputStream fis = new FileInputStream(txtExcelPath
						.getText());
				HSSFWorkbook wb = new HSSFWorkbook(fis);
				HSSFSheet sheet = wb.getSheetAt(row);
				Log.log("____ Evaluate sheet " + wb.getSheetName(row));
				ExcelAction excelAction = new ExcelAction(wb, sheet);
				EntityOverview table = excelAction.getOverviewInfo();
				// check if this sheet contain invalid data
				if (Util.isEmpty(table.getName())
						|| Util.isEmpty(table.getPackageName())
						|| Util.isEmpty(table.getDestPath())
						|| Util.isEmpty(table.getDestScreenPath())) {
					result = false;
					Log.log(Log.ERROR,"____ Sheet " + wb.getSheetName(row)
							+ " contain invalid data ");
				} else {
					ArrayList<Entity> listField = excelAction
							.getListDataTable();
					//Generate output dir with current datetime (yyyyMMddHHmm)
					String outputDir = Util.generateDatetimeDir(
							new File(Util.getParamConfig("FILE_OUT_LOCATION")).getAbsolutePath());
					
					new ModelCodegenAction(listField, table,outputDir);
					new IDAOCodegenAction(listField, table,outputDir);
					new DAOCodegenAction(listField, table,outputDir);
					new IActionCodegenAction(listField, table,outputDir);
					new ActionCodegenAction(listField, table,outputDir);
					new JsfAddCodegenAction(listField, table, outputDir);
					new JsfConfirmCodegenAction(listField, table, outputDir);
					new JsfResultCodegenAction(listField, table, outputDir);
					new JsfListCodegenAction(listField, table, outputDir);
					new XmlPageCodegenAction(listField, table, outputDir);
					new IndexPageCodegenAction(listField, table, outputDir);
					
					Log.log("____ Generated action, model, dao, jsf, xml, xhtml files successfully of sheet: "
									+ wb.getSheetName(row)+" to directory: " + outputDir);
					
					//copy src dir
					copySrcDir(outputDir,table.getDestPath());
					//copy web dir
					copyWebDir(outputDir,table.getDestScreenPath().substring(0,table.getDestScreenPath().lastIndexOf("\\")),
							Util.getWebbaseDir(table.getDestScreenPath()));
					result = true;
				}
			} catch (Exception e) {
				result = false;
				Log.log(Log.ERROR,"____ Error when generate files from sheet: "+ wb.getSheetName(row)
						+"\n" +e);
				e.printStackTrace();
			}
		}
		if (result)
			Message.showInfoMsg(this,
					"Generate files successfully");
		else
			Message.showErrorMsg(this,
					"Generate files failed. Please check log file");

	}
	/**
	 * Copy src dir (include action, dao, model) to destination dir
	 * @param srcFolder
	 * @param destSrcFolder
	 */
	private void copySrcDir(String srcFolder, String destSrcFolder) throws Exception {
		//copy src dir
		Log.log("Copy dir: "+ srcFolder
				+ System.getProperty("file.separator")+"src" +" to dir:" +destSrcFolder );
		Util.copyDirectory(new File(srcFolder
				+ System.getProperty("file.separator")+"src")
					, new File(destSrcFolder));
		
	}
	/**
	 * Copy web dir to destination dir
	 * @param webFolder
	 * @param destWebFolder
	 */
	private void copyWebDir(String webFolder, String destWebFolder, String webbaseDir)
		throws Exception {
		Log.log("Copy dir: "+ webFolder + System.getProperty("file.separator")+webbaseDir
				+" to dir:" +destWebFolder);
		//copy action dir
		Util.copyDirectory(new File(webFolder 
				+ System.getProperty("file.separator") + "WebContent"), new File(destWebFolder));
		
	}

	private void doExit() {
		int value = JOptionPane.showConfirmDialog(this, "Do you want to exit?",
				"MMGS", JOptionPane.YES_NO_OPTION);
		if (value == JOptionPane.YES_OPTION) {
			this.dispose();
			System.exit(0);
		}
	}
}
